package com.ruoyi.kanban.service.impl;

import java.util.List;
import java.util.Date;
import java.text.SimpleDateFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.kanban.mapper.SequenceNumberMapper;
import com.ruoyi.kanban.domain.SequenceNumber;
import com.ruoyi.kanban.service.ISequenceNumberService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.kanban.mapper.DeliveryOrderMapper;

/**
 * 流水号记录Service业务层处理
 *
 * @author ruoyi
 * @date 2025-01-15
 */
@Service
public class SequenceNumberServiceImpl implements ISequenceNumberService
{
    @Autowired
    private SequenceNumberMapper sequenceNumberMapper;

    @Autowired
    private DeliveryOrderMapper deliveryOrderMapper;

    /**
     * 查询流水号记录
     *
     * @param id 流水号记录主键
     * @return 流水号记录
     */
    @Override
    public SequenceNumber selectSequenceNumberById(Long id)
    {
        return sequenceNumberMapper.selectSequenceNumberById(id);
    }

    /**
     * 查询流水号记录列表
     *
     * @param sequenceNumber 流水号记录
     * @return 流水号记录
     */
    @Override
    public List<SequenceNumber> selectSequenceNumberList(SequenceNumber sequenceNumber)
    {
        return sequenceNumberMapper.selectSequenceNumberList(sequenceNumber);
    }

    /**
     * 新增流水号记录
     *
     * @param sequenceNumber 流水号记录
     * @return 结果
     */
    @Override
    public int insertSequenceNumber(SequenceNumber sequenceNumber)
    {
        return sequenceNumberMapper.insertSequenceNumber(sequenceNumber);
    }

    /**
     * 修改流水号记录
     *
     * @param sequenceNumber 流水号记录
     * @return 结果
     */
    @Override
    public int updateSequenceNumber(SequenceNumber sequenceNumber)
    {
        return sequenceNumberMapper.updateSequenceNumber(sequenceNumber);
    }

    /**
     * 批量删除流水号记录
     *
     * @param ids 需要删除的流水号记录主键
     * @return 结果
     */
    @Override
    public int deleteSequenceNumberByIds(Long[] ids)
    {
        return sequenceNumberMapper.deleteSequenceNumberByIds(ids);
    }

    /**
     * 删除流水号记录信息
     *
     * @param id 流水号记录主键
     * @return 结果
     */
    @Override
    public int deleteSequenceNumberById(Long id)
    {
        return sequenceNumberMapper.deleteSequenceNumberById(id);
    }

    /**
     * 生成临时流水号（不更新数据库）
     *
     * @param seqKey 流水号key
     * @param length 流水号长度
     * @return 临时流水号
     */
    @Override
    public String generateTempSequenceNumber(String seqKey, int length)
    {
        // 先根据当天已存在的发货单号计算最大后缀（如 SHYYYYMMDD-0008 => 8）
        Integer maxSuffix = deliveryOrderMapper.selectMaxSuffixBySeqKey(seqKey, length);
        long maxFromOrders = (maxSuffix != null) ? maxSuffix.longValue() : 0L;

        // 临时号仅根据当日已存在单据计算，以确保用户看到的是连续的下一号
        long nextSeq = maxFromOrders + 1;
        String seqStr = String.format("%0" + length + "d", nextSeq);

        // 直接使用传入的seqKey，不做任何修改
        return seqKey + "-" + seqStr;
    }

    /**
     * 生成正式流水号（更新数据库）
     *
     * @param seqKey 流水号key
     * @param length 流水号长度
     * @return 正式流水号
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String generateFormalSequenceNumber(String seqKey, int length)
    {
        // 最大重试次数
        int maxRetries = 10;
        int retryCount = 0;

        while (retryCount < maxRetries) {
            try {
                // 先计算当天已存在的发货单号的最大后缀
                Integer maxSuffix = deliveryOrderMapper.selectMaxSuffixBySeqKey(seqKey, length);
                long maxFromOrders = (maxSuffix != null) ? maxSuffix.longValue() : 0L;

                // 查询当前序列号
                SequenceNumber sequenceNumber = sequenceNumberMapper.selectSequenceNumberByKey(seqKey);
                if (sequenceNumber == null) {
                    // 如果不存在，创建新记录，初始值按当天已存在的最大后缀对齐
                    sequenceNumber = new SequenceNumber();
                    sequenceNumber.setSeqKey(seqKey);
                    sequenceNumber.setSeq(maxFromOrders);
                    sequenceNumber.setVersion(0);
                    sequenceNumber.setCreateTime(new Date());
                    sequenceNumber.setUpdateTime(new Date());
                    sequenceNumberMapper.insertSequenceNumber(sequenceNumber);
                    // 重新查询获取最新数据
                    sequenceNumber = sequenceNumberMapper.selectSequenceNumberByKey(seqKey);
                }

                // 如果序列表当前值超前于当天已存在的最大后缀，则尝试向下对齐（重置为 maxFromOrders）
                if (sequenceNumber.getSeq() > maxFromOrders) {
                    int reset = sequenceNumberMapper.resetSequenceToValue(
                        seqKey, sequenceNumber.getVersion(), maxFromOrders);
                    if (reset > 0) {
                        sequenceNumber.setSeq(maxFromOrders);
                        sequenceNumber.setVersion(sequenceNumber.getVersion() + 1);
                    } else {
                        // 重置失败（并发版本变化），重新获取最新数据后继续流程
                        sequenceNumber = sequenceNumberMapper.selectSequenceNumberByKey(seqKey);
                    }
                }

                // 如果序列表当前值落后于当天已存在的最大后缀，则用乐观锁逐步追平
                while (sequenceNumber.getSeq() < maxFromOrders) {
                    int bumpResult = sequenceNumberMapper.updateSequenceWithLock(
                        seqKey, sequenceNumber.getSeq(), sequenceNumber.getVersion());
                    if (bumpResult > 0) {
                        sequenceNumber.setSeq(sequenceNumber.getSeq() + 1);
                        sequenceNumber.setVersion(sequenceNumber.getVersion() + 1);
                    } else {
                        // 并发冲突或版本不匹配，重新获取最新数据
                        sequenceNumber = sequenceNumberMapper.selectSequenceNumberByKey(seqKey);
                        if (sequenceNumber == null) {
                            // 极端并发下记录被删除或未创建，重新按对齐值创建
                            SequenceNumber sn = new SequenceNumber();
                            sn.setSeqKey(seqKey);
                            sn.setSeq(maxFromOrders);
                            sn.setVersion(0);
                            sn.setCreateTime(new Date());
                            sn.setUpdateTime(new Date());
                            sequenceNumberMapper.insertSequenceNumber(sn);
                            sequenceNumber = sequenceNumberMapper.selectSequenceNumberByKey(seqKey);
                        }
                    }
                }

                // 使用乐观锁更新序列号
                int updateResult = sequenceNumberMapper.updateSequenceWithLock(
                    seqKey, sequenceNumber.getSeq(), sequenceNumber.getVersion());

                if (updateResult > 0) {
                    // 更新成功，生成流水号
                    long nextSeq = sequenceNumber.getSeq() + 1;
                    String seqStr = String.format("%0" + length + "d", nextSeq);

                    return seqKey + "-" + seqStr;
                } else {
                    // 更新失败，说明有并发冲突，重试
                    retryCount++;
                    if (retryCount >= maxRetries) {
                        throw new ServiceException("生成流水号失败，请重试");
                    }
                    // 短暂等待后重试
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        throw new ServiceException("生成流水号被中断");
                    }
                }
            } catch (Exception e) {
                retryCount++;
                if (retryCount >= maxRetries) {
                    throw new ServiceException("生成流水号异常：" + e.getMessage());
                }
            }
        }

        throw new ServiceException("生成流水号失败，超过最大重试次数");
    }
}
